﻿#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <dbHelper.h>
#include <QApplication>
#include <QSharedMemory>
#include <QFile>
#include <QTextCodec>
#include <amplprogram.h>
#include <QFontDatabase>
#include <QFont>
#include "setUp.h"
#include "mockInterface.h"
#include "experimentInfo.h"
#include "experimentPro.h"
#include "dataanalysis.h"
#include "runningChart.h"
#include "runningChartBar.h"
#include "wlkOperator.h"
#include <CommonHelper.h>
#include "QThread"
#include "uploadfile.h"
#include "maco.h"
#include "historyexperiment.h"
#include "saveExpInfo.h"
#include "qmlSignal.h"
#include "logHelperJ.h"
#include "keyEventFilter.h"

void onTimeout() {
    QSqlDatabase db = dbHelper::openConnection();
    QSqlQuery query(db);

    QString sql="Update StaticNumInfo Set RunningTime=(RunningTime*3600.0+60)/3600.0 Where EquGuid in(Select Id From EquipmentInfo Where  EquStatus in('1','2','3'))";
    query.exec(sql);
}

void initDatabase(){

    CommonHelper *common;
    common->commonInstance();

    //创建数据库
    QSqlDatabase db = dbHelper::openConnection();
    QSqlQuery query(db);

    db.transaction();
    QFile file(":/file/dbInfo.txt");
    QTextCodec* codec = QTextCodec::codecForName("GBK");
    file.open(QIODevice::ReadOnly | QIODevice::Text);

    QTextStream txtInput(&file);
    txtInput.setCodec(codec);
    while (!txtInput.atEnd())
    {
        QString lineStr = txtInput.readLine();
        query.exec(lineStr);
    }

    db.commit();


    QString sql="Select count(*) Num from IsFirstStartUp";
    query.exec(sql);

    bool isFirstStartUp = false;
    while (query.next()) {
        isFirstStartUp=query.value("Num").toInt()==0;
    }
    query.clear();

    if(isFirstStartUp)//第一次启动
    {
        sql="Insert into MixedJudgment values('R1','1.35'),('R2','1.5'),('R3','1.65'),('X1','0.003')";
        query.exec(sql);

        sql="Insert into IsFirstStartUp values('0',0,'12344312')";
        query.exec(sql);



        // 创建QFile对象，指定文件名
        QFile file("EqptInfo.xml");

        // 尝试打开文件以进行写入
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
            qWarning() << "无法打开文件：" << file.errorString();
            exit(1);
        }

        // 创建一个QTextStream对象来写入文件
        QTextStream out(&file);

        // 写入XML内容
        out << "<info>" << endl;
        out << "    <operh>00:00</operh>" << endl;//运行时长
        out << "    <operThre>1</operThre>"<<endl;
        out << "    <durah>00:00:00</durah>" << endl;//检测时长
        out << "    <duraThre>02:00:00</duraThre>"<<endl;
        out << "    <times>0</times>" << endl;//实验次数
        out << "    <timesThre>1000</timesThre>"<<endl;
        out << "    <sampelsum>0</sampelsum>" << endl;//总检测样本数
        out << "    <sampelsumThre>460</sampelsumThre>" << endl;
        out << "    <swlife>2.15</swlife>" << endl;
        out << "    <swtimes>3</swtimes>" << endl;
        out << "    <swname>RT-PCR-96 Analysis software V1.2</swname>" << endl;
        out << "    <steps>30</steps>" << endl;
        out << "    <password>111111</password>" << endl;
        out << "    <serverIp>192.168.0.10</serverIp>" << endl;
        out << "    <serverPort>8081</serverPort>" << endl;
        out << "</info>";

        // 关闭文件
        file.close();

        sql="INSERT INTO ItemCode (IsDefault,Name,Code,DicCode) "
            "VALUES (1,'Sample1',0,1),"
            "(0,'Sample2',1,1),"
            "(0,'Sample3',2,1),"
            "(0,'Sample4',3,1),"
            "(0,'Sample5',4,1);";
        query.exec(sql);
        sql="INSERT INTO ItemCode (IsDefault,Name,Code,DicCode) "
            "VALUES (0,'未知',0,2),"
            "(1,'标准',1,2),"
            "(0,'阴性',2,2);";
        query.exec(sql);

        sql="INSERT INTO ItemCode (Name,Code,DicCode) "
            "VALUES "
            "('A1',1,3),('B1',2,3),('C1',3,3),('D1',4,3),('E1',5,3),('F1',6,3),('G1',7,3),('H1',8,3),"
            "('A2',9,3),('B2',10,3),('C2',11,3),('D2',12,3),('E2',13,3),('F2',14,3),('G2',15,3),('H2',16,3),"
            "('A3',17,3),('B3',18,3),('C3',19,3),('D3',20,3),('E3',21,3),('F3',22,3),('G3',23,3),('H3',24,3),"
            "('A4',25,3),('B4',26,3),('C4',27,3),('D4',28,3),('E4',29,3),('F4',30,3),('G4',31,3),('H4',32,3),"
            "('A5',33,3),('B5',34,3),('C5',35,3),('D5',36,3),('E5',37,3),('F5',38,3),('G5',39,3),('H5',40,3),"
            "('A6',41,3),('B6',42,3),('C6',43,3),('D6',44,3),('E6',45,3),('F6',46,3),('G6',47,3),('H6',48,3),"
            "('A7',49,3),('B7',50,3),('C7',51,3),('D7',52,3),('E7',53,3),('F7',54,3),('G7',55,3),('H7',56,3),"
            "('A8',57,3),('B8',58,3),('C8',59,3),('D8',60,3),('E8',61,3),('F8',62,3),('G8',63,3),('H8',64,3),"
            "('A9',65,3),('B9',66,3),('C9',67,3),('D9',68,3),('E9',69,3),('F9',70,3),('G9',71,3),('H9',72,3),"
            "('A10',73,3),('B10',74,3),('C10',75,3),('D10',76,3),('E10',77,3),('F10',78,3),('G10',79,3),('H10',80,3),"
            "('A11',81,3),('B11',82,3),('C11',83,3),('D11',84,3),('E11',85,3),('F11',86,3),('G11',87,3),('H11',88,3),"
            "('A12',89,3),('B12',90,3),('C12',91,3),('D12',92,3),('E12',93,3),('F12',94,3),('G12',95,3),('H12',96,3);";
        query.exec(sql);

        sql="INSERT INTO ItemCode (IsDefault,Name,Code,DicCode) "
            "VALUES (1,'20','20ul',4),(0,'15','15ul',4),(0,'10','10ul',4),(0,'25','25ul',4),(0,'30','30ul',4);";
        query.exec(sql);

        sql="INSERT INTO ItemCode (Name,Code,DicCode)VALUES "
            "('A1',1,5),('A2',2,5),('A3',3,5),('A4',4,5),"
            "('B1',5,5),('B2',6,5),('B3',7,5),('B4',8,5),"
            "('C1',9,5),('C2',10,5),('C3',11,5),('C4',12,5),"
            "('D1',13,5),('D2',14,5),('D3',15,5),('D4',16,5),"
            "('E1',17,5),('E2',18,5),('E3',19,5),('E4',20,5),"
            "('F1',21,5),('F2',22,5),('F3',23,5),('F4',24,5);";
        query.exec(sql);

        sql="INSERT INTO ItemCode (IsDefault,Name,Code,DicCode) "
            "VALUES (1,'Pcr板',0,6),"
            "(0,'Pcr板裙边',1,6),"
            "(0,'Pcr管',2,6),"
            "(0,'8联排',3,6);";
        query.exec(sql);
        sql="INSERT INTO ItemCode (IsDefault,Name,Code,DicCode) "
            "VALUES (1,'FAM','F',7),(0,'SYBR Green','SG',7),"
            "(0,'Eva Green','EG',7),(1,'VIC','V',8),"
            "(0,'HEX','HEX',8),(0,'JOE','JOE',8),(1,'ROX','R',9),"
            "(0,'Texas Red','TR',9),(1,'CY5','C',10),(0,'Qusar 670','Q6',10),"
            "(0,'FAM','F',11),(0,'SYBR Green','SG',11),(0,'Eva Green','EG',11),"
            "(0,'VIC','V',11),(0,'HEX','HEX',11),(0,'JOE','JOE',11),"
            "(0,'ROX','R',11),(0,'Texas Red','TR',11),"
            "(1,'CY5','C',11),(0,'Qusar 670','Q6',11),(1,'明德试剂盒','1',12),"
            "(1,'7500','7500',13),(0,'7500线上','7500线上',13),(0,'鲲鹏','鲲鹏',13),"
            "(0,'Q5','Q5',13),(0,'Q5英文版','Q5英文版',13),(0,'伯乐','伯乐',13),(0,'Design and Analysis-线下版','Design and Analysis-线下版',13),"
            "(1,'3500XL','3500XL',14),(0,'3500','3500',14),(0,'SeqStudio 24Flex','SeqStudio 24Flex',14),"
            "(0,'3130XL','3130XL',14),(0,'3130','3130',14),"
            "(1,'常STR','16',15),(0,'Y-STR','17',15),(0,'Mini-STR','18',15),"
            "(1,'Verifiler Plus','Verifiler Plus',16),(0,'PP21','PP21',16),(0,'PP27','PP27',16),"
            "(0,'GlobalFiler','GlobalFiler',16),(0,'ID','ID',16),(0,'ID plus','ID plus',16),"
            "(0,'BTY25A','BTY25A',16),(0,'海尔施S6','海尔施S6',16),(1,'Y41白金','Y41白金',17),"
            "(0,'海尔施Y40','海尔施Y40',17),(0,'BTY44Y案件','BTY44Y案件',17),(0,'BTY44Y建库','BTY44Y建库',17),"
            "(1,'新海NHID Mini 25A ','新海NHID Mini 25A ',18),(0,'BTY13A','BTY13A',18),"
            "(1,'10','10',19),(0,'15','15',19),(0,'25','25',19),(0,'30','30',19),(1,'100','100',20),"
            "(1,'./datao','./datao',100);";
        query.exec(sql);

        CommonHelper* common;
        QXlsx::Document xlsx(":/Template/Default Template.xlsx");
        QStringList sheetList = xlsx.sheetNames();

        QSqlDatabase db = dbHelper::openConnection();
        QSqlQuery query(db);

        db.transaction();
        for (int i=0;i<sheetList.count();i++) {
            xlsx.selectSheet(sheetList[i]);
            QXlsx::Worksheet *worksheet = xlsx.currentWorksheet();

            QString jyfxyq = worksheet->read("A3").toString();//基因分析仪
            QString reagentKitType =worksheet->read("B3").toString();//试剂盒类型
            QString reagentKitName =worksheet->read("C3").toString();//试剂盒名称
            QString system =worksheet->read("D3").toString();//体系
            QString memo =worksheet->read("E3").toString();//备注

            QString sql=QString("Select Name From ItemCode Where DicCode=(Select Code From ItemCode Where Name='%1')").arg(reagentKitType);
            query.exec(sql);
            bool canImport=false;
            while (query.next()) {
                if(query.value("Name").toString()==reagentKitName)
                {
                    canImport=true;
                }
            }

            if(canImport){
                QString configGuid="";

                int num;
                sql=QString("Select Count(*) as Num From DataAnalyseConfig Where GeneticAnalysers='%1' and ReagentKitType='%2' and ReagentKitName='%3' and System='%4' ").arg(jyfxyq,reagentKitType,reagentKitName,system);
                query.exec(sql);
                while (query.next()) {
                    num=query.value("Num").toInt();
                }

                if(num>0)
                {
                    QString oldModelGuid;
                    sql=QString("Select ID,ModelGuid From DataAnalyseConfig Where GeneticAnalysers='%1' and ReagentKitType='%2' and ReagentKitName='%3' and System='%4' ").arg(jyfxyq,reagentKitType,reagentKitName,system);
                    query.exec(sql);
                    while (query.next())
                    {
                        configGuid=query.value("ID").toString();
                        oldModelGuid=query.value("ModelGuid").toString();
                    }

                    sql=QString("Delete From ModelConfigurationNormal Where ID='%1'").arg(oldModelGuid);
                    query.exec(sql);

                    sql=QString("Delete From ModelConfigurationY Where ID='%1'").arg(oldModelGuid);
                    query.exec(sql);

                    sql=QString("Delete From ModelConfigurationMini Where ID='%1'").arg(oldModelGuid);
                    query.exec(sql);
                }
                else
                {
                    configGuid =common->GetGuid();
                }

                if(reagentKitType=="常STR"){
                    QString modelGuid=common->GetGuid();
                    sql=QString("Insert into ModelConfigurationNormal Values('%1','%2','%3','%4')").arg(modelGuid,"0","检测方案",worksheet->read("F3").toString());
                    query.exec(sql);
                    sql=QString("Insert into ModelConfigurationNormal Values('%1','%2','%3','%4')").arg(modelGuid,"0","备注",worksheet->read("G3").toString());
                    query.exec(sql);

                    for (int m=5;m<24;m++) {
                        sql=QString("Insert into ModelConfigurationNormal Values('%1','%2','%3','%4')").arg(modelGuid,"1",worksheet->read("A"+QString::number(m)).toString(),worksheet->read("B"+QString::number(m)).toString());
                        query.exec(sql);
                    }

                    QString createTime=common->GetDateTimeStr();
                    sql=QString("Insert or replace into DataAnalyseConfig Values('%1','%2','%3','%4','%5','%6','%7','%8')").arg(configGuid,jyfxyq,reagentKitType,reagentKitName,system,modelGuid,createTime,memo);
                    query.exec(sql);
                }
                else if(reagentKitType=="Y-STR"){

                    QString modelGuid=common->GetGuid();

                    for (int m=5;m<20;m++) {
                        sql=QString("Insert into ModelConfigurationY Values('%1','%2','%3')").arg(modelGuid,worksheet->read("A"+QString::number(m)).toString(),worksheet->read("B"+QString::number(m)).toString());
                        query.exec(sql);
                    }

                    QString createTime=common->GetDateTimeStr();
                    sql=QString("Insert or replace into DataAnalyseConfig Values('%1','%2','%3','%4','%5','%6','%7','%8')").arg(configGuid,jyfxyq,reagentKitType,reagentKitName,system,modelGuid,createTime,memo);

                    query.exec(sql);

                }else if(reagentKitType=="Mini-STR"){

                    QString modelGuid=common->GetGuid();

                    for (int m=5;m<18;m++) {
                        sql=QString("Insert into ModelConfigurationMini Values('%1','%2','%3')").arg(modelGuid,worksheet->read("A"+QString::number(m)).toString(),worksheet->read("B"+QString::number(m)).toString());
                        query.exec(sql);
                    }

                    QString createTime=common->GetDateTimeStr();
                    sql=QString("Insert or replace into DataAnalyseConfig Values('%1','%2','%3','%4','%5','%6','%7','%8')").arg(configGuid,jyfxyq,reagentKitType,reagentKitName,system,modelGuid,createTime,memo);
                    query.exec(sql);
                }
            }
        }
        db.commit();
    }
}

int main(int argc, char *argv[])
{
    QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    QApplication app(argc, argv);
    QDir dir;
    if (!dir.exists("./dataout/")) {
        dir.mkpath("./dataout/"); // 创建目录，包括所有必要的上级目录
    }

#ifdef Q_OS_WINDOWS
    QSharedMemory shared_memory;
    shared_memory.setKey(QString("123465"));
    if (shared_memory.attach()) {
        QMessageBox::information(nullptr,"提示","软件已经启动");
        qWarning("Another instance is already running.");
        return 0;
    }
    if (!shared_memory.create(1)) {
        qWarning("Failed to create shared memory segment.");
        return -1;
    }
    SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);
#endif

    int fontId = QFontDatabase::addApplicationFont(":/fonts/AlibabaPuHuiTi-3-55-Regular.ttf");      // 字体设置
    if(fontId != -1){
        QStringList fontFamilies = QFontDatabase::applicationFontFamilies(fontId);
        if(fontFamilies.isEmpty()){
            qDebug("设置字体失败2");
        }
        QString familyName = fontFamilies.first();
        QFont font(familyName, 10);
        app.setFont(font);
    }else{
        qDebug("设置字体失败");
    }

    initDatabase();

    QQmlApplicationEngine engine;
    const QUrl url(QStringLiteral("qrc:/mainpage/main.qml"));
    QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                     &app, [url](QObject *obj, const QUrl &objUrl) {
        if (!obj && url == objUrl)
            QCoreApplication::exit(-1);
    }, Qt::QueuedConnection);
    engine.load(url);



    // =================================== QML接口类 ==========================================
    Amplprogram* amplProgram = new Amplprogram();
    engine.rootContext()->setContextProperty("CAmplProgram", amplProgram);

    SetUp* setup = new SetUp();
    engine.rootContext()->setContextProperty("CSetUp", setup);

    ExperimentInfo* expInfo = new ExperimentInfo();
    engine.rootContext()->setContextProperty("CExpInfo", expInfo);

    ExperimentPro* expPro = new ExperimentPro();
    engine.rootContext()->setContextProperty("CExpPro", expPro);

    MockInterface* mockInterface = new MockInterface();
    engine.rootContext()->setContextProperty("CMock", mockInterface);
    mockInterface->engine = &engine;

    // 数据分析运行中的和本地打开分为两个类，关闭动态Anchor绑定，show事件重写
    DataAnalysis* analysis = new DataAnalysis();        // 运行中数据分析
    engine.rootContext()->setContextProperty("CAnalysis", analysis);

    WlkOperator* wlkO = new WlkOperator();
    engine.rootContext()->setContextProperty("CWlk", wlkO);

    UploadFile* uploadfile = new UploadFile();
    engine.rootContext()->setContextProperty("CULF", uploadfile);

    maco *maint = new maco();
    engine.rootContext()->setContextProperty("MACO", maint);

    QStringList filetype = uploadfile->kzyqname();
    engine.rootContext()->setContextProperty("filetype", QVariant::fromValue(filetype));
    engine.load(QUrl(QStringLiteral("DialogOther.qml")));
    QStringList jyfxytype = uploadfile->jyfxyname();
    engine.rootContext()->setContextProperty("jyfxytype", QVariant::fromValue(jyfxytype));
    engine.load(QUrl(QStringLiteral("DialogOther.qml")));

    engine.rootContext()->setContextProperty("CSignal", &(QMLSignal::I()));

#ifdef Q_OS_WINDOWS
    // 运行中图表
    RunningChart* runningChart = new RunningChart();
    engine.rootContext()->setContextProperty("CRunningChart", runningChart);
    runningChart->expPro = expPro;
    runningChart->engine = &engine;
    runningChart->mock = mockInterface;
    RunningChartBar* runningChartBar = new RunningChartBar();
    engine.rootContext()->setContextProperty("CRunningChartBar", runningChartBar);
    runningChartBar->expPro = expPro;
    runningChartBar->mock = mockInterface;
    runningChartBar->engine = &engine;

    SaveExpInfo* saveInfo = new SaveExpInfo();
    engine.rootContext()->setContextProperty("CSaveInfo", saveInfo);

    HistoryExperiment* historyExp = new HistoryExperiment();
    engine.rootContext()->setContextProperty("CHistory", historyExp);
#endif

    // 键盘监听
    KeyEventFilter* kef = new KeyEventFilter();
    engine.rootContext()->setContextProperty("CKeyEvent", kef);
    //    QObject* qmlMainWindow = engine.rootObjects().first()->findChild<QObject*>("mainwindow");
    QList<QObject*> objs = engine.rootObjects();
    QObject* qmlMainWindow = engine.rootObjects().first();
    qmlMainWindow->installEventFilter(kef);

    // ===================================== 接口类结束 ==========================================


    setup->connectAll();
    QTimer timer;

    // 连接定时器的 timeout 信号到槽函数 onTimeout
    QObject::connect(&timer, &QTimer::timeout, &onTimeout);
    // 启动定时器，每隔 1000 毫秒触发一次
    timer.start(60000);

    QQuickWindow::setSceneGraphBackend(QSGRendererInterface::Software);     // 窗口圆角设置

    LogHelperJ::write(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
    LogHelperJ::write(">>>  Start-Up QPCRMulti Software  >>>");
    LogHelperJ::write(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
    app.exec();
    qDebug() << "APP退出";

    return 0;
}


